#include "../../inc/skyPainter.h"
#ifdef _GLES_
#include "../thirdParty/win32/ogles/gles/gl.h"
#include "../thirdParty/win32/ogles/EGL/egl.h"
#include "./glApp.h"
namespace GL
{
	using namespace Sky;
    template <typename T>
    struct Point2D
    {
    public:
        typedef T Type;
        const static int Dimension = 2;
        Point2D(T _x,T _y):x(_x),y(_y){}
    public:
        T x;
        T y;
    };
    template <typename T>
    struct Point3D
    {
    public:
        typedef T Type;
        const static int Dimension = 3;
        Point3D(T _x,T _y,T _z = 0):x(_x),y(_y),z(_z){}
    public:
        T x;
        T y;
        T z;
    };

    template <typename T>
    struct Rect
    {
    public:
        typedef T type;

        Rect(T _x,T _y,T _w,T _h):x(_x),y(_y),w(_w),h(_h){}
    public:
        T x;
        T y;
        T w;
        T h;
    };

    #define PointD Point2D
    typedef PointD<int> iPoint;
    typedef PointD<float> fPoint;
    typedef PointD<unsigned int> uPoint;

    typedef Rect<int> iRect;
    typedef Rect<float> fRect;
    typedef Rect<unsigned int> uRect;

    class Float
    {
    public:
        Float(float f):v(f){}
        GLfloat v;
        const static int GLType = GL_FLOAT;
    };

    class Color
    {
    public:
        const static int Dimension = 4;
        const static int GLType = GL_UNSIGNED_BYTE;
        typedef GLbyte Type;
        typedef unsigned char u8;
        Color(){}
        Color(u8 _r,u8 _g,u8 _b,u8 _a = 255):r(_r),g(_g),b(_b),a(_a){}
    public:
        GLbyte r;
        GLbyte g;
        GLbyte b;
        GLbyte a;
    };

    
    static Color lineColor;
    static Color brushColor;

    template <typename T>
    int GL_(){return GL_FLOAT;}

    typedef Rect<GLfloat> fRect;
    typedef Rect<GLfixed> xRect;

    typedef PointD<GLfloat> fPoint;

    typedef PointD<GLfixed> xPoint;

    typedef PointD<GLfloat> fCoord;


	//////////////////////////////////////////////////////////////////////////

	void DrawLine(GL::fPoint x,GL::fPoint y,Color color);

	void DrawLine(GL::fPoint* points,int numb)
	{
		glDisable(GL_TEXTURE_2D);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glEnableClientState(GL_VERTEX_ARRAY);

		glVertexPointer(GL::fPoint::Dimension, GL::GL_<GL::fPoint::Type>(), 0, points);	
		glDrawArrays(GL_LINE_STRIP, 0, numb);

		glEnableClientState(GL_COLOR_ARRAY);
		glEnable(GL_TEXTURE_2D);
	}

	void DrawLine(GL::fPoint* points,int numb,Color color);

	void DrawLine(GL::fPoint* points,int numb,Color* colors);

	void DrawRect(GL::fRect rect,Color color);

	void DrawRect(GL::fRect rect,Color* colors);

	void DrawPoly(GL::fPoint* points,int numb,Color color);

	void DrawPoly(GL::fPoint* points,int numb,Color* colors);
	//////////////////////////////////////////////////////////////////////////
    void DrawPoint(GL::fPoint* point,int numb)
    {
        glDisable(GL_TEXTURE_2D);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);

        glVertexPointer(GL::fPoint::Dimension, GL::GL_<GL::fPoint::Type>(), 0, point);	
        glDrawArrays(GL_POINTS, 0, numb);

        // restore default state
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnable(GL_TEXTURE_2D);
    };

    void DrawPoint(GL::fPoint* point,int numb,Color color)
    {
        glDisable(GL_TEXTURE_2D);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

        //glColorPointer(Color::Dimension,GL::GL_<Color::Type>(),0,color);
        glVertexPointer(GL::fPoint::Dimension, GL::GL_<GL::fPoint::Type>(), 0, point);	
        glDrawArrays(GL_POINTS, 0, numb);

        glEnableClientState(GL_COLOR_ARRAY);
        glEnable(GL_TEXTURE_2D);
    };

    void DrawPoint(GL::fPoint* point,int numb,Color* colors);

    //////////////////////////////////////////////////////////////////////////
    void DrawLine(GL::fPoint x,GL::fPoint y)
    {
        GL::fPoint vertices[2] = {x,y};
        return DrawLine(vertices,2);
    }

	void DrawLine( fPoint* points,int numb,Color color )
	{

	}

    void DrawLine(GL::fPoint x,GL::fPoint y,Color color);

	void DrawLine(GL::fPoint* points,int numb);

    void DrawLine(GL::fPoint* points,int numb,Color color);

    void DrawLine(GL::fPoint* points,int numb,Color* colors);

    //////////////////////////////////////////////////////////////////////////

    void DrawRect(GL::fRect rect)
    {
        GL::fPoint x1(rect.x,rect.y),x2(rect.x + rect.w,rect.y),x3(rect.x + rect.w,rect.y + rect.h),x4(rect.x,rect.y + rect.h);
        GL::fPoint vertices[5] = {x1,x2,x3,x4,x1};
        DrawLine(vertices,5);
    }

	void DrawRect( fRect rect,Color color )
	{
		GL::fPoint x1(rect.x,rect.y),x2(rect.x + rect.w,rect.y),x3(rect.x + rect.w,rect.y + rect.h),x4(rect.x,rect.y + rect.h);
		GL::fPoint vertices[5] = {x1,x2,x3,x4,x1};
		DrawLine(vertices,5,color);
	}

    void DrawRect(GL::fRect rect,Color color);

    void DrawRect(GL::fRect rect,Color* colors);

    void DrawPoly(GL::fPoint* points,int numb,Color color);

    void DrawPoly(GL::fPoint* points,int numb,Color* colors);

    //////////////////////////////////////////////////////////////////////////
    void FillRect(GL::fRect rect)
    {
        //GL::fPoint x1(rect.x,rect.y),x2(rect.x + rect.w,rect.y),x3(rect.x + rect.w,rect.y + rect.h),x4(rect.x,rect.y + rect.h);
        GLfloat vertices[] =
		{
			rect.x,rect.y,
			rect.x + rect.w,rect.y,
			rect.x + rect.w,rect.y + rect.h,
			rect.x,rect.y + rect.h
		};
        //Color c(0,0,0,125);
        //Color colors[5] = {c,c,c,c,c};

		glEnable (GL_BLEND);

        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisable(GL_TEXTURE_2D);

        glVertexPointer(2, GL_FLOAT, 0, vertices);
        //glColorPointer(Color::Dimension, Color::GLType, 0, colors);

        //glBlendFunc(GL_ONE_MINUS_DST_ALPHA,GL_SRC_ALPHA );

        glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);

        //if( newBlend )
        //    glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);

        // restore default GL state
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnable(GL_TEXTURE_2D);
    }

	void BlendRect(GL::fRect rect,Color color)
	{
		GLfloat vertices[] =
		{
			rect.x,rect.y,
			rect.x ,rect.y + rect.h,
			rect.x + rect.w,rect.y ,
			rect.x + rect.w,rect.y + rect.h
		};

		Color colors[] = {color,color,color,color};
		glEnable(GL_BLEND);
		glBlendFunc(GL_ZERO , GL_SRC_COLOR);

		glDisable(GL_TEXTURE_2D);

		glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_VERTEX_ARRAY);

		glVertexPointer(2, GL_FLOAT, 0, vertices);

		glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);

		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	}

    void FillRect(GL::fRect rect,Color color)
    {
        GLfloat vertices[] =
		{
			rect.x,rect.y,
			rect.x ,rect.y + rect.h,
			rect.x + rect.w,rect.y ,
			rect.x + rect.w,rect.y + rect.h
		};

		Color colors[] = {color,color,color,color};
		glDisable(GL_BLEND);
		glDisable(GL_COLOR_LOGIC_OP);
		glDisable(GL_TEXTURE_2D);

        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_VERTEX_ARRAY);

		glVertexPointer(2, GL_FLOAT, 0, vertices);

        glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);

        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        
    }

    void FillPoly(GL::fPoint* points,int numb,Color color);

    void FillRect(GL::fRect rect,GL::fCoord* coord,int numb);

    void FillPoly(GL::fPoint* points,GL::fCoord* coord,int numb);
}
namespace Sky
{

	Void Painter::drawLine( Point& start,Point& end )
	{
		DrawLine(GL::fPoint(start.x,start.y),GL::fPoint(end.x,end.y));
	}

	Void Painter::drawPict( Rect& dstRect,Pict* iPict,Rect* srcRect )
	{
		glBindTexture(GL_TEXTURE_2D, iPict->getTexture());

		GLfloat vertex[8]={	dstRect.x,dstRect.y,
							dstRect.x,dstRect.y + dstRect.h,
							dstRect.x + dstRect.w,dstRect.y,
							dstRect.x + dstRect.w,dstRect.y + dstRect.h
				};

		const GLfloat squareTextureCoords[] = {
			0, 0,       // bottom left
			0, 1,       // top left
			1, 0,       // bottom right
			1, 1        // top right
		};

		glColor4ub(255,255,255,255);

		glEnable (GL_BLEND);

		glBlendFunc(GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA);

		glEnableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		
		glEnable(GL_TEXTURE_2D);

		glVertexPointer(2, GL_FLOAT, 0, vertex);
		glTexCoordPointer(2, GL_FLOAT, 0, squareTextureCoords);

		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
		glDisable(GL_BLEND);

	}

	Void Painter::drawText(Rect& rect,const String* text,Color color,Layout::Align align) 
	{
		//m_Sprite.draw(const_cast<String*>(text)->toCharString(),&rect,-1,align,D3DCOLOR_RGBA(color.r,color.g,color.b,color.a));
	}

	Void Painter::setPenColor( Color color )
	{
		//D3DXCOLOR clr = D3DCOLOR_RGBA(color.r,color.g,color.b,color.a);
		//m_Pen.setColor(clr);
		glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
	}

	Painter::Painter()
	{
		GL::lineColor = GL::Color(0,0,0,255);
		GL::brushColor = GL::Color(0,0,0,255);
	}

	Bool Painter::begin()
    {
		do 
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
			//////////////////////////////////////////////////////////////////////////

			E_Break_If(eglReleaseTexImage(GL::getContext()->m_eglDisplay, mCanvas->getSurface(), EGL_BACK_BUFFER) 
				== EGL_FALSE);

			E_Break_If(eglMakeCurrent(GL::getContext()->m_eglDisplay, mCanvas->getSurface(), mCanvas->getSurface(), GL::getContext()->m_eglContext)
				== EGL_FALSE);
			
			//glMatrixMode(GL_PROJECTION);
			//glOrthox(-(mCanvas->getSize().w/2)<<16, (mCanvas->getSize().w/2)<<16, -(mCanvas->getSize().h/2)<<16, (mCanvas->getSize().h/2)<<16, -128<<16, 128<<16);

			
			glClearColorx(0, 0x10000, 0x10000, 0);
			glClear(GL_COLOR_BUFFER_BIT);

			return vTrue;
		} while (0);

		xAssert(GL_NO_ERROR == glGetError());
		return vFalse;
	}

	Void Painter::end()
	{
		//do 
		//{
		//	//////////////////////////////////////////////////////////////////////////

		//	E_Break_If(!eglMakeCurrent(GL::getContext()->m_eglDisplay, GL::getContext()->m_eglSurface,GL::getContext()->m_eglSurface, GL::getContext()->m_eglContext));

		//	glBindTexture(GL_TEXTURE_2D, mCanvas->getPict()->getTexture());

		//	E_Break_If(!eglBindTexImage(GL::getContext()->m_eglDisplay, mCanvas->getSurface(), EGL_BACK_BUFFER));

		//	glBindTexture(GL_TEXTURE_2D, mCanvas->getPict()->getTexture());

		//	int Width,Height;

		//	eglQuerySurface(GL::getContext()->m_eglDisplay, GL::getContext()->m_eglSurface,EGL_WIDTH,  (EGLint*)&Width);

		//	eglQuerySurface(GL::getContext()->m_eglDisplay, GL::getContext()->m_eglSurface,EGL_HEIGHT, (EGLint*)&Height);

		//	E_Break_If(!eglMakeCurrent(GL::getContext()->m_eglDisplay, GL::getContext()->m_eglSurface, GL::getContext()->m_eglSurface, GL::getContext()->m_eglContext));

		//	//glMatrixMode(GL_PROJECTION);

		//	int N_PLANE_W = Width;
		//	int N_PLANE_H = Height;

		//	//glOrthox(-(N_PLANE_W/2)<<16, (N_PLANE_W/2)<<16, -(N_PLANE_H/2)<<16, (N_PLANE_H/2)<<16, -128<<16, 128<<16);

		//	glClearColorx(0x10000, 0x10000, 0, 0);

		//	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

		//	GLfloat vertex[12]={
		//		-200.0f,-200.0f,0,
		//		-200.0f,200.0f,0,
		//		200.0f,-200.0f,0,
		//		200.0f,200.0f,0};
		//	const GLfloat squareTextureCoords[] = {
		//		0, 0,			// bottom left
		//		0, 1.0f,		// top left
		//		1.0f, 0,		// bottom right
		//		1.0f, 1.0f      // top right
	
		//	};

		//	glEnableClientState(GL_VERTEX_ARRAY);
		//	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		//	glDisableClientState(GL_COLOR_ARRAY);
		//	glEnable(GL_TEXTURE_2D);

		//	glVertexPointer(3, GL_FLOAT, 0, vertex);
		//	glTexCoordPointer(2, GL_FLOAT, 0, squareTextureCoords);

 	//		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

		//	glDisable(GL_TEXTURE_2D);
		//	glDisableClientState(GL_VERTEX_ARRAY);
		//	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		//	
		//	E_Break_If(eglSwapBuffers (GL::getContext()->m_eglDisplay, GL::getContext()->m_eglSurface)
		//		== EGL_FALSE);
		//	return;

		//} while (0);
		//xAssert(vNull);
		return;

	}

	Sky::NType::Void Painter::present( Pict* pict )
	{
		do 
		{
			//////////////////////////////////////////////////////////////////////////

			glBindTexture(GL_TEXTURE_2D, pict->getTexture());

			E_Break_If(!eglBindTexImage(GL::getContext()->m_eglDisplay, mCanvas->getSurface(), EGL_BACK_BUFFER));

			E_Break_If(!eglMakeCurrent(GL::getContext()->m_eglDisplay, GL::getContext()->m_eglSurface,GL::getContext()->m_eglSurface, GL::getContext()->m_eglContext));

			int Width,Height;

			eglQuerySurface(GL::getContext()->m_eglDisplay, GL::getContext()->m_eglSurface,EGL_WIDTH,  (EGLint*)&Width);

			eglQuerySurface(GL::getContext()->m_eglDisplay, GL::getContext()->m_eglSurface,EGL_HEIGHT, (EGLint*)&Height);

			int N_PLANE_W = Width;
			int N_PLANE_H = Height;

			GLbyte colors[] = {
				0,255,0,0,
				0,0,255,0,
				0,255,255,0,
				255,0,255,255
			};

			
			glClearColorx(0x10000, 0, 0, 0);

			glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
			
#define  BORDER_DLTA 5.0f

			GLfloat vertex[]={
				-Width/2 + BORDER_DLTA,-Height/2 + BORDER_DLTA,0,
				-Width/2 + BORDER_DLTA, Height/2 - BORDER_DLTA,0,
				Width/2  - BORDER_DLTA,-Height/2 + BORDER_DLTA,0,
				Width/2  - BORDER_DLTA, Height/2 - BORDER_DLTA,0};

			GLfloat rationW = (GLfloat)Width/(GLfloat)pict->getSize().w;
			GLfloat rationH = (GLfloat)Height/(GLfloat)pict->getSize().h;

			const GLfloat squareTextureCoords[] = {
					0, 0,				// bottom left
					0, rationH,			// top left
					rationW, 0,			// bottom right
					rationW,rationH      // top right

				};
				glColor4ub(255,255,255,0);
				glDisable(GL_BLEND);
				glEnableClientState(GL_VERTEX_ARRAY);
				glEnableClientState(GL_TEXTURE_COORD_ARRAY);
				glDisableClientState(GL_COLOR_ARRAY);
				glEnable(GL_TEXTURE_2D);

				glVertexPointer(3, GL_FLOAT, 0, vertex);
				glTexCoordPointer(2, GL_FLOAT, 0, squareTextureCoords);
				glColorPointer(4,GL_UNSIGNED_BYTE,0,colors);

				glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

				E_Break_If(eglSwapBuffers (GL::getContext()->m_eglDisplay, GL::getContext()->m_eglSurface)
					== EGL_FALSE);
				return;

		} while (0);
		xAssert(vNull);
		return;
	}

	Void Painter::fillRect( Rect& rect )
	{
        FillRect(GL::fRect(rect.x,rect.y,rect.w,rect.h));
	}

	Void Painter::setBrushColor( Color color )
	{
		GL::brushColor = GL::Color(color.r,color.g,color.b,color.a);
	}

	Bool Painter::attachPict( Pict* iPict )
	{
		return vFalse;
	}

	Pict* Painter::detachPict()
	{
		PictPtr prev = mpPict;
		mpPict = vNull;
		return prev;
	}

	Bool Painter::attachFont( Font* iFont )
	{
		mpFont = iFont;
		return vTrue;
	}

	Font* Painter::detachFont()
	{
		FontPtr prev = mpFont;
		mpFont = vNull;
		return prev;
	}

	Bool Painter::fillWith( Pict* srcPict,Rect* srcRect,Rect* dstRect )
	{
		return vTrue;
	}

	Bool Painter::mirrorWith( Pict* srcPict,Pict* dst,u32 MirrorType_)
	{
		return vTrue;
	}

	Void Painter::drawRect( Rect& rect )
	{
        return GL::DrawRect(GL::fRect(rect.x,rect.y,rect.w,rect.h));
	}


	Void Painter::fillRect( Rect& rect,Color color )
	{
		return GL::FillRect(GL::fRect(rect.x,rect.y,rect.w,rect.h),GL::Color(color.r,color.g,color.b,color.a));
	}

	Sky::NType::Void Painter::blendRect( Rect& rect,Color color )
	{
		return GL::BlendRect(GL::fRect(rect.x,rect.y,rect.w,rect.h),GL::Color(color.r,color.g,color.b,color.a));
	}

	Void Painter::drawRect( Rect& rect,Color color )
	{
		GL::DrawRect(GL::fRect(rect.x,rect.y,rect.w,rect.h),GL::Color(color.r,color.g,color.b,color.a));
	}

	Size Painter::calTextSize( String* str ,Font* font)
	{
		Rect r;
		r.x = 0;
		r.y = 0;
		FontPtr oldFont;
		if(font != vNull)
		{
			oldFont = getFont();
			attachFont(font);
		}
		Size ret ;//= m_Sprite.calTextSize(&mpFont->getFont(),str->toCharString(),&r);
		if(font != vNull)
		{
			attachFont(oldFont);
		}
		return Size(ret.w,ret.h);
	}

	Sky::Bool Painter::attachCanvas( Canvas* canvas )
	{
		mCanvas = canvas;
		return vTrue;
	}

	Canvas* Painter::detachCanvas()
	{
		Canvas* p = mCanvas;
		mCanvas = vNull;
		return p;
	}

	OSPainter::OSPainter()
	{

	}

	OSPainter::~OSPainter()
	{

	}

}
#endif
